package com.bjtu.ptsite.controller;

import com.bjtu.ptsite.model.InviteCode;
import com.bjtu.ptsite.model.PageResult;
import com.bjtu.ptsite.model.Result;
import com.bjtu.ptsite.model.User;
import com.bjtu.ptsite.model.UserDTO;
import com.bjtu.ptsite.service.InviteCodeService;
import com.bjtu.ptsite.service.PointsService;
import com.bjtu.ptsite.service.UserService;
import com.bjtu.ptsite.utils.AliOSSUtils;
import com.bjtu.ptsite.utils.JwtUtils;
import com.bjtu.ptsite.utils.RequestUtil;
import com.bjtu.ptsite.utils.RequestUtil.UserContext;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.math.BigDecimal;
import java.util.Objects;

import javax.validation.Valid;

/**
 *
 * @author Zehao Wang, Junjie Zhang, Yutao Wei
 *
 */
@CrossOrigin
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    private static final int MIN_INVITE_CODE_LENGTH = 8;
    private static final int MIN_USER_LEVEL = 4;
    private static final int POINTS_DEDUCTION = 50;
    @Autowired
    private UserService userService;
    @Autowired
    private PointsService pointsService;
    @Autowired
    private InviteCodeService inviteCodeService;
    @Autowired
    private AliOSSUtils aliOssUtils;
    private static final String ROLE_ADMINISTRATOR = "admin";

    /**
     *
     * 个人资料接口
     *
     */
    @GetMapping("/profile")
    public Result getProfile() {
        Integer userId = RequestUtil.getUserContext().getId();

        // 查询用户信息
        User user = userService.getUserById(userId);

        // 敏感信息过滤，移除密码字段
        user.setPassword(null);

        return Result.success(user);
    }

    @GetMapping("/getAvatar")
    public Result getAvatar() {
        Integer userId = RequestUtil.getUserContext().getId();

        String avatar = userService.getAvatarById(userId);

        return Result.success(avatar);
    }

    /**
     *
     * 修改个人资料
     *
     */
    @PutMapping("/profile")
    public Result updateProfile(@RequestBody @Valid UserDTO updateDTO) {
        // 获取当前用户ID
        int userId = RequestUtil.getUserContext().getId();

        // 执行更新
        User updatedUser = userService.updateUserProfile(userId, updateDTO);

        // 过滤敏感字段
        updatedUser.setPassword(null);

        return Result.success(updatedUser);
    }

    @PostMapping("/password")
    public Result resetPassword(@RequestBody Map<String, String> params) {
        int userId = RequestUtil.getUserContext().getId();
        String email = userService.getUserById(userId).getEmail();
        String newPassword = params.get("newPassword");
        String verificationCode = params.get("verificationCode");

        if (newPassword == null || verificationCode == null) {
            return Result.error("参数不完整");
        }

        if (!userService.verifyCode(email, verificationCode)) {
            return Result.error("验证码错误");
        }

        userService.resetPassword(userId, newPassword);
        return Result.success("密码修改成功");
    }

    @PostMapping("/resetVerification")
    public Result resetVerification() {
        int userId = RequestUtil.getUserContext().getId();
        String email = userService.getUserById(userId).getEmail();

        // 发送验证码
        userService.sendVerificationCode(email, 1);
        return Result.success("验证码已发送");
    }

    /**
     *
     * 他人资料接口
     *
     */
    @GetMapping("/{userId}/profile")
    public Result getPublicProfile(@PathVariable int userId) {
        int curUserId = RequestUtil.getUserContext().getId();
        User curUser = userService.getUserById(curUserId);
        // 查询目标用户
        User targetUser = userService.getUserById(userId);

        if (targetUser == null) {
            return Result.error("用户不存在");
        }

        if (!curUser.getRole().equals(ROLE_ADMINISTRATOR)) {
            // 过滤敏感信息
            targetUser.setSeedPoints(999999);
            targetUser.setUploadGB(999999);
            targetUser.setPassKey("敏感信息");
            targetUser.setUploadedDelta(9999990);
            targetUser.setDownloadedDelta(999999);
            targetUser.setSharingRate(BigDecimal.valueOf(0.9999));
            targetUser.setAssessDay(999);
            targetUser.setDailyAward(false);
            targetUser.setUploadAssess(9999990);
            targetUser.setUnactivateDay(0);
        }
        targetUser.setPassword("敏感信息");
        if (userService.isFollowExits(curUserId, userId)) {
            targetUser.setFollowed(true);
        } else {
            targetUser.setFollowed(false);
        }
        return Result.success(targetUser);
    }

    @PostMapping("/uploadAvatar")
    public Result uploadAvatar(@RequestParam("file") MultipartFile file) throws IOException {
        // 1. 上传文件到OSS
        String url = aliOssUtils.upload(file);

        // 2. 获取当前登录用户ID
        int userId;
        userId = RequestUtil.getUserContext().getId();

        String curAvatar = userService.getAvatarById(userId);
        if (curAvatar != null && !curAvatar
                .equals("https://avatar-wzh.oss-cn-beijing.aliyuncs.com/51e0ff55-4166-4870-baad-fff1705cd3ea.png")) {
            aliOssUtils.deleteFileByUrl(curAvatar);
        }

        // 3. 更新数据库中的头像路径
        userService.updateAvatar(userId, url);

        return Result.success(url);
    }

    @PostMapping("/createInviteCode")
    public Result createInviteCode(@RequestBody Map<String, String> params) {
        try {
            String code = params.get("code");
            if (code.length() < MIN_INVITE_CODE_LENGTH) {
                return Result.error("邀请码不得少于" + MIN_INVITE_CODE_LENGTH + "位");
            }
            int userId = RequestUtil.getUserContext().getId();

            User user = userService.getUserById(userId);
            if ((user.getLevel() < MIN_USER_LEVEL) && (!ROLE_ADMINISTRATOR.equals(user.getRole()))) {
                return Result.error("只有" + MIN_USER_LEVEL + "级及以上用户可以生成邀请码");
            }

            if (user.getSeedPoints() < POINTS_DEDUCTION) {
                return Result.error("积分不足");
            }
            if (inviteCodeService.getInviteCode(code) != null
                    && code.equals(inviteCodeService.getInviteCode(code).getCode())) {
                return Result.error("邀请码已存在");
            }
            pointsService.deductPoints(userId, POINTS_DEDUCTION);
            InviteCode inviteCode = inviteCodeService.createInviteCode(user, code);
            return Result.success(inviteCode);
        } catch (RuntimeException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            return Result.error("系统错误添加失败");
        }
    }

    @PostMapping("/addInviteCodeUses")
    public Result addInviteCode(@RequestBody Map<String, String> params) {
        try {
            String code = params.get("code");
            int userId = RequestUtil.getUserContext().getId();
            User user = userService.getUserById(userId);
            InviteCode inviteCode = inviteCodeService.addInviteCode(user, code);
            pointsService.deductPoints(userId, 100);
            return Result.success(inviteCode);
        } catch (RuntimeException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            return Result.error("系统错误添加失败");
        }
    }

    @PostMapping("/deleteInviteCode")
    public Result deleteInviteCode(@RequestBody Map<String, String> params) {
        try {
            String code = params.get("code");
            int userId = RequestUtil.getUserContext().getId();
            User user = userService.getUserById(userId);
            if (inviteCodeService.deleteInviteCode(user, code)) {
                return Result.success("删除邀请码 " + code + " 成功");
            }
            ;
            return Result.error("删除邀请码 " + code + " 失败");
        } catch (RuntimeException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            return Result.error("系统错误添加失败");
        }
    }

    @GetMapping("/getInviteCode")
    public Result getInviteCode() {
        int userId = RequestUtil.getUserContext().getId();
        User user = userService.getUserById(userId);
        List<InviteCode> inviteCodes = inviteCodeService.getCodes(user);
        if (inviteCodes == null) {
            return Result.error("您还未拥有邀请码");
        }
        return Result.success(inviteCodes);
    }

    @PostMapping("/follow/{userId}")
    public Result followUser(@PathVariable int userId) {
        int curUserId = RequestUtil.getUserContext().getId();
        if (userService.getUserById(userId) == null) {
            return Result.error("被关注的用户不存在");
        }
        if (curUserId == userId) {
            return Result.error("请不要关注自己");
        }
        if (userService.isFollowExits(curUserId, userId)) {
            return Result.error("您已关注此用户");
        }
        userService.followUser(curUserId, userId);
        return Result.success("关注成功");
    }

    @PostMapping("/deFollow/{userId}")
    public Result deFollowUser(@PathVariable int userId) {
        int curUserId = RequestUtil.getUserContext().getId();
        if (userService.getUserById(userId) == null) {
            return Result.error("被关注的用户不存在");
        }
        if (curUserId == userId) {
            return Result.error("你是怎么做到发送这个请求的？");
        }
        if (!userService.isFollowExits(curUserId, userId)) {
            return Result.error("您还未关注此用户");
        }
        userService.deFollowUser(curUserId, userId);
        return Result.success("取消关注成功");
    }

    @GetMapping("/follows")
    public Result getFollows() {
        int userId = RequestUtil.getUserContext().getId();
        List<UserDTO> followsList = userService.getFollows(userId);
        return Result.success(followsList);
    }

    @GetMapping("/fans")
    public Result getFans() {
        int userId = RequestUtil.getUserContext().getId();
        List<UserDTO> fansList = userService.getFans(userId);
        return Result.success(fansList);
    }

    @PostMapping("/ban/{userId}")
    public Result banUser(@PathVariable int userId) {
        int curUserId = RequestUtil.getUserContext().getId();
        User curUser = userService.getUserById(curUserId);
        User user = userService.getUserById(userId);
        if (!Objects.equals(curUser.getRole(), ROLE_ADMINISTRATOR)) {
            return Result.error("你不是管理员，不过我更好奇你是怎么发送这个请求的");
        }
        if(ROLE_ADMINISTRATOR.equals(user.getRole())){
            return Result.error("请不要封禁管理员");
        }
        if (curUserId == userId) {
            return Result.error("你为什么要封禁自己?");
        }
        if (user.isBaned() == true) {
            return Result.error("该用户已被封禁，请不要鞭尸");
        }
        userService.banUser(userId);
        return Result.success("用户" + user.getUsername() + "已成功封禁");
    }

    @PostMapping("/unban/{userId}")
    public Result unbanUser(@PathVariable int userId) {
        int curUserId = RequestUtil.getUserContext().getId();
        User curUser = userService.getUserById(curUserId);
        User user = userService.getUserById(userId);
        if (!Objects.equals(curUser.getRole(), ROLE_ADMINISTRATOR)) {
            return Result.error("你不是管理员，不过我更好奇你是怎么发送这个请求的");
        }
        if(ROLE_ADMINISTRATOR.equals(user.getRole())){
            return Result.error("管理员是怎么被封的?");
        }
        if (curUserId == userId) {
            return Result.error("你是怎么做到把自己封了的?");
        }
        if (user.isBaned() == false) {
            return Result.error("俺寻思他也没被封啊");
        }
        userService.unbanUser(userId);
        return Result.success("用户 " + user.getUsername() + " 已成功解封");
    }

    @GetMapping("/getUserList")
    public Result getUserList(@RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        int curUserId = RequestUtil.getUserContext().getId();
        User curUser = userService.getUserById(curUserId);
        if(!ROLE_ADMINISTRATOR.equals(curUser.getRole())){
            return Result.error("你不是管理员，不过我更好奇你是怎么发送这个请求的");
        }
        PageResult<User> userList = userService.getUserList(page, size);
        return Result.success(userList);
    }
}
